package com.itdct.mto.core.base;

import com.itdct.mto.core.bo.ColumnBo;
import com.itdct.mto.core.bo.IndexBo;
import com.itdct.mto.core.bo.PartitionBo;
import com.itdct.mto.core.bo.TableBo;
import com.itdct.mto.core.config.MtoConfig;
import com.itdct.mto.core.context.Context;
import com.itdct.mto.core.exception.MtoException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;

import lombok.extern.slf4j.Slf4j;

/**
 * @author Zhouwx
 * @date 2025/7/2 9:50:39
 * @version 1.0
 * @description
 */
@Slf4j
@Component
public class BaseManager {
    @Autowired
    protected JdbcTemplate mysqlJdbcTemplate;
    @Autowired
    protected JdbcTemplate postgresJdbcTemplate;
    @Autowired
    protected MtoConfig mtoConfig;
    @Autowired
    protected ThreadPoolExecutor threadPoolExecutor;

    public void error(String message) throws RuntimeException {
        throw new MtoException(message);
    }

    protected void init(Context context) {
        if (context.isInitTables()) {
            return;
        }

        List<String> tableNames = context.getTableNames();
        if (tableNames == null) {
            ArrayList<String> tables = new ArrayList<>();
            context.setTableNames(tables);
            tableNames = tables;
            mysqlJdbcTemplate.query("show tables;", (rs) -> {
                String tableName = rs.getString(1);
                tables.add(tableName);
            });
        }

        if (tableNames.isEmpty()) {
            error("数据库内没有表！");
            return;
        }

        // INFO: Zhouwx: 2025/7/3 如果指定表了，就用指定的表去处理
        List<String> specificTableNames = mtoConfig.getSpecificTableNames();
        if (specificTableNames != null && !specificTableNames.isEmpty()) {
            // tableNames和specificTableNames的交集
            specificTableNames.retainAll(tableNames);
            if (specificTableNames.isEmpty()) {
                error("指定的表不存在！");
            }

            tableNames.clear();
            tableNames.addAll(specificTableNames);
        }

        analyzeTables(context);

        context.setInitTables(true);
    }

    protected void analyzeTables(Context context) {
        log.info("开始分析表结构");
        context.setAnalyseStartTime(System.currentTimeMillis());
        List<String> tableNames = context.getTableNames();
        CountDownLatch countDownLatch = new CountDownLatch(tableNames.size());
        List<String> filterTableNames = mtoConfig.getFilterTableNames();
        List<String> failTableNames = context.getFailTableNames();

        for (String tableName : tableNames) {
            if (filterTableNames != null && filterTableNames.contains(tableName)) {
                log.info("表名：{}，已过滤，跳过", tableName);
                countDownLatch.countDown();
                continue;
            }

            TableBo tableBo = new TableBo();
            context.getTableBos().add(tableBo);

            threadPoolExecutor.submit(() -> {
                try {
                    mysqlJdbcTemplate.query("show create table " + tableName, rs -> {
                        // INFO: Zhouwx: 2025/7/2 获取所有表名的ddl信息
                        String tableDdl = rs.getString(2);
                        tableBo.setTableDdl(tableDdl);
                        analyseDdl(tableDdl, tableBo);
                        tableBo.setAnalyseSuccess(true);
                    });
                } catch (Exception e) {
                    log.error("表名：{}，执行失败", tableName);
                    log.error("", e);
                    tableBo.setAnalyseSuccess(false);
                    tableBo.setException(e);
                    failTableNames.add(tableName);
                } finally {
                    countDownLatch.countDown();
                }
            });

        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            log.error("", e);
        }
        context.setAnalyseEndTime(System.currentTimeMillis());
        log.info("完成分析表结构，总共：{} 张表，失败 {} 张表", tableNames.size(), failTableNames.size());
    }

    protected void analyseDdl(String tableDdl, TableBo tableBo) {
        String[] lines = tableDdl.split("\n");
        String createTableLine = lines[0];

        String tableName = createTableLine.substring(createTableLine.indexOf("`") + 1, createTableLine.lastIndexOf("`"));
        tableBo.setTableName(tableName);

        for (int i = 1; i < lines.length; i++) {
            String line = lines[i].trim();
            if (line.endsWith(",")) {
                // INFO: Zhouwx: 2025/7/1 去掉结尾逗号导致的问题
                line = line.substring(0, line.length() - 1);
            }

            if (line.contains("KEY ")) {
                // INFO: Zhouwx: 2025/7/1 索引信息
                IndexBo indexBo = new IndexBo();
                tableBo.getIndexList().add(indexBo);
                if (line.contains("PRIMARY KEY")) {
                    // INFO: Zhouwx: 2025/7/1 主键
                    String columnName = line.substring(line.indexOf("`") + 1, line.lastIndexOf("`"));
                    columnName = columnName.replace("`", "");
                    indexBo.setColumns(columnName);
                    indexBo.setIndexName("PRIMARY");
                    indexBo.setIndexType("PRIMARY KEY");
                    String finalColumnName = columnName;
                    tableBo.getColumnList()
                            .stream()
                            .filter(columnBo -> columnBo.getColumnName().equals(finalColumnName))
                            .forEach(columnBo -> {
                                columnBo.setPrimaryKey(true);
                            });
                } else {
                    // INFO: Zhouwx: 2025/7/1 普通索引，包含unique索引
                    if (line.startsWith("UNIQUE")) {
                        indexBo.setIndexType("UNIQUE KEY");
                    } else {
                        indexBo.setIndexType("KEY");
                    }
                    // INFO: Zhouwx: 2025/7/1 排除乱七八糟Key带来的影响
                    line = line.substring(line.indexOf("KEY") + 3).trim();
                    String[] splitSpace = line.split(" ");

                    indexBo.setIndexName(splitSpace[0]);
                    String columns = splitSpace[1];
                    columns = columns.substring(columns.indexOf("(") + 1, columns.lastIndexOf(")"));
                    indexBo.setColumns(columns);
                }
            } else if (line.startsWith(") ENGINE")) {
                // INFO: Zhouwx: 2025/7/1 说明是表最后的说明信息，包含了Engine和Comment等
                if (line.contains("COMMENT")) {
                    String tableComment = line.substring(line.indexOf("'") + 1, line.lastIndexOf("'"));
                    tableBo.setTableComment(tableComment);
                }
            } else if (line.contains("PARTITION")) {
                // INFO: Zhouwx: 2025/7/1 解析分区信息
                tableBo.setPartitionTable(true);
                if (line.contains("PARTITION BY")) {
                    // INFO: Zhouwx: 2025/7/1 获取partition by的相关信息
                    String partitionBy = line.substring(line.indexOf("PARTITION BY") + 13).trim();
                    tableBo.setPartitionBy(partitionBy);
                } else {
                    // INFO: Zhouwx: 2025/7/1 单个partition内容
                    if (tableBo.isPartitionTable()) {
                        if (line.startsWith("(")) {
                            line = line.substring(1);
                        }
                        line = line.substring("PARTITION ".length()).trim();
                        line = line.substring(0, line.indexOf("ENGINE")).trim();
                        int spaceIndex = line.indexOf(" ");

                        PartitionBo partitionBo = new PartitionBo();
                        tableBo.getPartitionList().add(partitionBo);
                        String partitionName = line.substring(0, spaceIndex);
                        partitionBo.setPartitionName(partitionName);
                        partitionBo.setPartitionValue(line.substring(spaceIndex + 1)
                                .replace("VALUES", "")
                                .trim());
                    } else {
                        // INFO: Zhouwx: 2025/7/1 非分区表，不需要处理分区信息
                    }
                }
            } else {
                // INFO: Zhouwx: 2025/7/1 列信息
                ColumnBo columnBo = new ColumnBo();
                tableBo.getColumnList().add(columnBo);
                String columnName = line.substring(line.indexOf("`") + 1, line.lastIndexOf("`"));
                columnBo.setColumnName(columnName);

                // INFO: Zhouwx: 2025/7/1 排除列名的影响
                line = line.substring(line.lastIndexOf("`") + 1);

                // INFO: Zhouwx: 2025/7/1 获取列注释信息
                if (line.contains("COMMENT")) {
                    String columnComment = line.substring(line.lastIndexOf("COMMENT") + 9, line.lastIndexOf("'"));
                    columnBo.setColumnComment(columnComment);

                    // INFO: Zhouwx: 2025/7/1 排除列注释造成的影响
                    line = line.substring(0, line.lastIndexOf("COMMENT"));
                    line = line.trim();
                }
                line = line.trim();

                String[] splitSpace = line.split(" ");
                columnBo.setColumnType(splitSpace[0]);

                if (line.contains("AUTO_INCREMENT")) {
                    columnBo.setAutoIncrement(true);
                }

                if (line.contains("NOT NULL")) {
                    columnBo.setNotNull(true);
                }

                if (line.contains("DEFAULT")) {
                    int defaultValueIndex = 0;
                    for (int spaceIndex = 0; spaceIndex < splitSpace.length; spaceIndex++) {
                        String item = splitSpace[spaceIndex];
                        if (item.equals("DEFAULT")) {
                            defaultValueIndex = spaceIndex + 1;
                            break;
                        }
                    }
                    if (defaultValueIndex > 0) {
                        columnBo.setColumnDefault(splitSpace[defaultValueIndex]);
                    }
                }
            }
        }
    }

}
